package cn.bonoon.kernel.web.handlers;

import javax.servlet.ServletContext;

import org.springframework.context.ApplicationContext;

import cn.bonoon.handler.AutoManager;
import cn.bonoon.kernel.events.OperateEvent;
import cn.bonoon.kernel.support.OperandSupport;
import cn.bonoon.kernel.support.services.LogWriterService;
import cn.bonoon.kernel.web.models.JsonResult;

/**
 * <pre>
 * 每一个操作的处理（操作处理指的是需要修改到数据库的操作）的实现都应该继承于本父类
 * 每一个操作都应该定义操作的范围，操作的范围分为：
 * 全局范围
 * 所属域范围
 * 专属范围
 * 
 * 操作指对数据记录进行编辑的事件，使用{@link OperateEvent}
 * 需要指定操作数{@link AbstractOperateHandler#operandCode}，操作数的定义见接口{@link OperandSupport}
 * 
 * 操作处理器，应该自动写操作日志
 * </pre>
 * @author jackson
 *
 */
public abstract class AbstractOperateHandler extends AbstractExecuteHandler implements OperandSupport{
	/**
	 * 当前操作实例对象的操作数，即操作的类型，如：修改、移动等类型
	 */
	protected final int operandCode;
	@Deprecated
	protected final String operateName;
	private LogWriterService logWriter;
	protected final ApplicationContext applicationContext;
	protected final ServletContext servletContext;
	
	protected AbstractOperateHandler(int operandCode, String operateName, AutoManager contextInitializer) {
		super("ajax");
		this.operandCode = operandCode;
		this.operateName = operateName;
		this.applicationContext = contextInitializer.getApplicationContext();
		this.servletContext = contextInitializer.getServletContext();
		this.logWriter = applicationContext.getBean(LogWriterService.class);
	}
	
	/**
	 * <pre>
	 * 操作处理器；操作处理器的功能包括：
	 * 1.操作权限限制
	 * 2.操作范围的限制
	 * 3.写操作日志
	 * 4.单个用户使用同步锁
	 * 5.解析处理结果
	 * </pre>
	 * @throws Exception 
	 */
	public final Object execute(OperateEvent event) throws Exception {
//		try{
			//TODO 这里是提交处理操作，所以需要判断下两次操作的session是否是同一个，如果不是同一个，则不应该提交
			Object result;
			synchronized (event.lock) {
				result = internalExecute(event);
			}
			success(event, result);
			return result(event, result);
//		}catch(PersistenceException ex){
//			ex.printStackTrace();
//			return JsonResult.error("数据库异常，无法提交数据！");
//		}catch(Exception ex){
//			ex.printStackTrace();
//			return JsonResult.error(ex.getCause());
//		}
	}
	
	protected void success(OperateEvent event, Object result){
		if(null != logWriter){
			try{
				logWriter.log(event, "操作:" + operateName + "; " + result.toString());
			}catch(Exception ex){
				//写日志，这里不管日志是否写成功，都不应该影响到业务操作
				event.error(ex.getCause());
			}
		}
	}
	/**
	 * 子类可以重写需要通过ajax返回到界面的数据
	 * @param event
	 * @param result
	 * @return
	 */
	protected JsonResult result(OperateEvent event, Object result){
		return JsonResult.result();
	}
	
	protected abstract Object internalExecute(OperateEvent event)throws Exception;
	
	public String getOperateName() {
		return operateName;
	}
	
	public int getOperandCode() {
		return operandCode;
	}
}
